import type {
  RequestFailResult,
  RequestResult,
} from "@done-coding/request-axios";
import {
  createRequest,
  RequestFailResultBusiness,
} from "@done-coding/request-axios";
import { ElMessage } from "element-plus";
import {
  APP_REQUEST_CONFIG,
  BusinessErrorEnum,
  goToLogin,
  refreshToken,
  getToken,
  refreshAuth,
} from "@/config";
import type { listCurrentPageKey, listPageSizeKey } from "@/config";

export const request = createRequest<{
  code: number;
  data: any;
  message: string;
}>({
  basePath: APP_REQUEST_CONFIG.basePath,
  timeout: APP_REQUEST_CONFIG.timeout,
  businessSuccessCodeList: [200],
  getBusinessCode: ({ data }) => {
    return data.code;
  },
  getBusinessData: ({ data }) => {
    return data.data;
  },
  getBusinessMsg: ({ data }) => {
    return data.message;
  },
  beforeRequest: (config) => {
    if (!config.headers.get("Authorization")) {
      config.headers.set("Authorization", getToken());
    }
    config.headers.set("X-Terminal", 1);
    return config;
  },
  beforeError: async (currentError) => {
    // 业务问题
    if (currentError.isBusinessError) {
      switch (currentError.code) {
        case BusinessErrorEnum.TOKEN_EXPIRED: {
          try {
            await refreshToken();
            return {
              reload: true,
            };
          } catch (error) {
            let canShowErrorToast = true;

            // 刷新token报错未登录
            if (
              error instanceof RequestFailResultBusiness &&
              error.code === BusinessErrorEnum.NOT_LOGIN
            ) {
              canShowErrorToast = false;
            }
            return {
              canShowErrorToast,
              newError: error as RequestFailResult,
            };
          }
        }
        case BusinessErrorEnum.NOT_LOGIN:
        case BusinessErrorEnum.KICK_OUT_BY_TERMINAL:
        case BusinessErrorEnum.USER_DISABLE:
        case BusinessErrorEnum.ABNORMAL_FALLBACK_TO_NOT_LOGIN: {
          goToLogin();
          return {
            // 不再提示错误信息
            canShowErrorToast:
              currentError.code !== BusinessErrorEnum.NOT_LOGIN,
            newError: currentError,
          };
        }
        case BusinessErrorEnum.NOT_AUTHORIZED: {
          refreshAuth();
          return {
            newError: currentError,
          };
        }
        default: {
          return {
            newError: currentError,
          };
        }
      }
    } else {
      // 非业务问题
      return {
        newError: currentError,
      };
    }
  },
  showToast: (message) => {
    ElMessage.error(message);
  },
  uiConfig: {
    errorToast: true,
  },
});

export type UnPackResult<T> =
  T extends Promise<RequestResult<infer I>> ? Promise<I> : never;

/** api扩展 */
export const apiExtend = <
  T,
  Fn extends (...args: any[]) => Promise<RequestResult<T>>,
>(
  api: Fn,
) => {
  return Object.assign(api, {
    /** (直接)解包 */
    unpack: (...args: Parameters<Fn>) => {
      return api(...args).then((res) => res.data) as UnPackResult<
        ReturnType<Fn>
      >;
    },
  });
};

/** 获取列表参数 */
export type GetListParams<P extends Record<string, any> = Record<string, any>> =
  {
    /** 当前页码 */
    [listCurrentPageKey]: number;
    /** 每页条数 */
    [listPageSizeKey]: number;
  } & Partial<P>;

/** 获取列表响应 */
export interface GetListResponse<T> {
  list: T[];
  total: number;
  [listCurrentPageKey]: number;
  [listPageSizeKey]: number;
}
